package org.bdware.registry.webService.service;

import com.google.gson.Gson;
import org.apache.log4j.Logger;
import org.bdware.doip.core.doipMessage.DoipMessage;
import org.bdware.doip.core.doipMessage.DoipMessageFactory;
import org.bdware.doip.core.doipMessage.DoipResponseCode;
import org.bdware.doip.endpoint.doipClient.DoipClient;
import org.bdware.doip.endpoint.doipClient.SyncDOAClient;
import org.bdware.doip.endpoint.doipServer.DoipServiceInfo;
import org.bdware.irp.exception.IrpClientException;
import org.bdware.registry.handler.BDRegistryHandler;
import org.bdware.registry.main.BDRegistry;
import org.bdware.registry.storage.RemoteReg;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.HashMap;

@Service
public class RegistryService {
    BDRegistryHandler handler = BDRegistry.getRegistryHandler();
    DoipServiceInfo doipInfo = BDRegistry.getInfo();
    static Logger logger = Logger.getLogger(RegistryService.class);
    SyncDOAClient doaClient;

    public RegistryService() throws InterruptedException {
        int count = 0;
        while(handler == null || doipInfo == null){
            logger.info("wait for DOIP Service initialization");
            Thread.sleep(1000);
            if(count++>5) break;
        }
        if(handler == null || doipInfo == null){
            logger.error("DOIP Service not initialized.");
        }
    }

    public String getRegInfo(){
        return doipInfo.toJson();
    }

    public HashMap<String,String> getInRegistry(){
        return handler.getInRegs();
    }

    public Collection<RemoteReg> getOutRegistry(){
        return handler.getOutRegs().values();
    }

    public boolean addRemoteRegistry(String regID, int level) throws IrpClientException {
        logger.info("==add reg: " + regID + " ," + level);
        DoipClient doipClient = getDoaClient().getDoipClient(regID);
        RemoteReg toAdd = new RemoteReg(regID,doipClient.getRepoUrl(),level);
        logger.info("now regs: " + new Gson().toJson(handler.getInRegs()));
        if(handler.getInRegs().containsKey(regID)){
            RemoteReg r = handler.getOutRegs().get(regID);
            //原本以引接方式接入，现在要退出
            if(r.equals(toAdd) && r.indexLevel ==1 && toAdd.indexLevel != 1){
                DoipMessage req = new DoipMessageFactory.DoipMessageBuilder()
                        .createRequest(regID,"Op.Quit")
                        .addAttributes("repoID",doipInfo.id)
                        .addAttributes("repoUrl",doipInfo.listenerInfos.get(0).url)
                        .create();
                DoipMessage resp = getDoaClient().sendRaw(req, regID);
                logger.debug("-quit response code: " + resp.header.parameters.response.getName());
                logger.debug("-quit response body: " + resp.body.getDataAsJsonString());
                if(resp.header.parameters.response == DoipResponseCode.Success){
                    handler.addOutRegs(toAdd);
                    return true;
                }
            }else if(r.indexLevel == toAdd.indexLevel) return true;
        }
        if(level == 1){
            DoipMessage req = new DoipMessageFactory.DoipMessageBuilder()
                    .createRequest(regID,"Op.Join")
                    .addAttributes("repoID",doipInfo.id)
                    .addAttributes("repoUrl",doipInfo.listenerInfos.get(0).url)
                    .create();
            logger.info(new Gson().toJson(req));
            DoipMessage resp = getDoaClient().sendRaw(req, regID);
            logger.info("-join response code: " + resp.header.parameters.response.getName());
            logger.info("-join response body: " + resp.body.getDataAsJsonString());
            if(resp.header.parameters.response == DoipResponseCode.Success){
                handler.addOutRegs(new RemoteReg(regID,doipClient.getRepoUrl(),level));
                return true;
            }
            logger.warn("add remote registry failed: " + resp.header.parameters.response.getName());
            return false;
        }else{
            handler.addOutRegs(new RemoteReg(regID,doipClient.getRepoUrl(),level));
            return true;
        }
    }

    public boolean testRemoteRegConnection(String regID) throws IrpClientException{
        DoipMessage msg = getDoaClient().hello(regID);
        logger.info("test connection: " + msg);
        return msg.header.parameters.response == DoipResponseCode.Success;
    }


    private SyncDOAClient getDoaClient() throws IrpClientException {
        if(doaClient == null)
            doaClient = new SyncDOAClient(2000);
        return doaClient;
    }
}
